﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace System.Windows.Forms
{
    /// <summary>
    /// 设计具有独特外观的ComboBox控件
    /// </summary>
    /// <see langword="Change ComboBox Border Color in Windows Forms" href="https://9to5answer.com/change-combobox-border-color-in-windows-forms"/>
    /// <see langword="WinForm窗体程序 重写 ComboBox 改选择框样式" href="https://blog.csdn.net/weixin_39237340/article/details/112915718"/>
    /// <creator>marc</creator>
    public class ShapeComboBox : ComboBox
    {
        private const int WM_PAINT = 0xF;
        /// <summary>
        /// 鼠标滚轮
        /// </summary>
        private const int WM_MOUSEWHEEL = 0x020A;

        private readonly int _buttonWidth = SystemInformation.HorizontalScrollBarArrowWidth;

        private Color _borderColor = Color.FromArgb(133, 145, 162);
        /// <summary>
        /// 边框颜色
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [Description("边框颜色")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public Color BorderColor
        {
            get { return _borderColor; }
            set { _borderColor = value; Invalidate(); }
        }

        private Font _drowdownFont = new Font("微软雅黑", 9);
        /// <summary>
        /// 下拉列表的字体
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [Description("下拉列表的字体")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public Font DropdownFont
        {
            get
            {
                return _drowdownFont;
            }
            set
            {
                _drowdownFont = value;
            }
        }

        private Color _dropdownBackColor = Color.FromArgb(245, 247, 254);
        //private Color _dropdownBackColor = Color.FromArgb(252, 252, 252);
        /// <summary>
        /// 下拉列表的背景色
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [Description("下拉列表的背景色")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public Color DropdownBackColor
        {
            get
            {
                return _dropdownBackColor;
            }
            set
            {
                _dropdownBackColor = value;
            }
        }

        private Color _itemBorderColor = Color.FromArgb(229, 195, 101);
        /// <summary>
        /// 下拉项的边框色
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [Description("下拉项的边框色")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public Color ItemBorderColor
        {
            get
            {
                return _itemBorderColor;
            }
            set
            {
                _itemBorderColor = value;
            }
        }

        private int _imageWidth = 25;
        /// <summary>
        /// 若有前导图片时，该图片的绘制宽度
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [DefaultValue(25)]
        [Description("若有前导图片时，该图片的绘制宽度")]
        public int ImageWidth
        {
            get
            {
                return _imageWidth;
            }
            set
            {
                _imageWidth = value;
            }
        }

        private int _imageHeight = 25;
        /// <summary>
        /// 若有前导图片时，该图片的绘制高度
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [DefaultValue(25)]
        [Description("若有前导图片时，该图片的绘制高度")]
        public int ImageHeight
        {
            get
            {
                return _imageHeight;
            }
            set
            {
                _imageHeight = value;
            }
        }

        /// <summary>
        /// 是否显示下拉竖线
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [DefaultValue(false)]
        [Description("是否显示下拉竖线")]
        public bool ShowDropLine { get; set; }

        /// <summary>
        /// 禁用鼠标滚轮
        /// </summary>
        [Browsable(true)]
        [Category("Xejen")]
        [DefaultValue(false)]
        [Description("禁用鼠标滚轮")]
        public bool ForbiddenMouseWheel { get; set; }

        /// <inheritdoc cref="ShapeComboBox"/>
        public ShapeComboBox()
        {
            //自绘组合框需要设置的一些属性
            this.DrawMode = DrawMode.OwnerDrawVariable;
        }

        /// <inheritdoc/>
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_PAINT && DropDownStyle != ComboBoxStyle.Simple)
            {
                DrawHorizontalScrollLine();
            }

            if (ForbiddenMouseWheel && m.Msg == WM_MOUSEWHEEL)
            {
                return;
            }

            base.WndProc(ref m);
        }

        /// <summary>
        /// 绘制下拉列表的竖线
        /// </summary>
        private void DrawHorizontalScrollLine()
        {
            using (var g = Graphics.FromHwnd(Handle))
            {
                using (var p = new Pen(BorderColor))
                {
                    g.DrawRectangle(p, 0, 0, Width - 1, Height - 1);

                    //绘制下拉的竖线
                    if (ShowDropLine)
                    {
                        var d = FlatStyle == FlatStyle.Popup ? 1 : 0;
                        g.DrawLine(p, Width - _buttonWidth - d, 0, Width - _buttonWidth - d, Height);
                    }
                }
            }
        }

        /// <inheritdoc/>
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            base.OnDrawItem(e);

            Graphics g = e.Graphics;// this.CreateGraphics();//

            //Debug.WriteLine(e.State);
            //鼠标选中在这个项上
            if ((e.State & DrawItemState.Selected) != 0)
            {
                if ((e.State & DrawItemState.ComboBoxEdit) == 0)
                {
                    //Debug.WriteLine("中国：" + e.State);
                    //渐变画刷
                    LinearGradientBrush brush = new LinearGradientBrush(e.Bounds, Color.FromArgb(255, 251, 237), Color.FromArgb(255, 236, 181), LinearGradientMode.Vertical);
                    //填充区域
                    Rectangle borderRect = new Rectangle(2, e.Bounds.Y + 1, e.Bounds.Width - 5, e.Bounds.Height - 2);

                    g.FillRectangle(brush, borderRect);
                    //下拉项鼠标移上去时的项边框颜色
                    Pen pen = new Pen(ItemBorderColor);
                    g.DrawRectangle(pen, borderRect);
                }
                else
                {
                    //Debug.WriteLine("来了：" + e.State);
                }
            }
            else
            {
                //下拉列表背景色
                SolidBrush brush = new SolidBrush(DropdownBackColor);
                g.FillRectangle(brush, e.Bounds);
            }

            if (e.Index == -1)
            {
                return;
            }

            //获得项图片,绘制图片
            ItemData data = (ItemData)this.Items[e.Index];
            Image img = data.Image;

            //图片绘制的区域
            Rectangle imgRect;
            if (img != null)
            {
                imgRect = new Rectangle(6, e.Bounds.Y + 3, ImageWidth, ImageHeight);
                g.DrawImage(img, imgRect);
            }
            else
            {
                imgRect = new Rectangle(6, e.Bounds.Y + 3, 0, 0);
            }
            //文本内容显示区域
            Rectangle textRect = new Rectangle(imgRect.Right + 2, imgRect.Y, e.Bounds.Width - imgRect.Width, e.Bounds.Height - 2);

            //文本格式垂直居中
            StringFormat strFormat = new StringFormat();
            strFormat.LineAlignment = StringAlignment.Center;
            g.DrawString(data.Text, DropdownFont, Brushes.Black, textRect, strFormat);
        }

        /// <inheritdoc/>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            Refresh();
        }

        /// <summary>
        /// 表示下拉项填充的数据
        /// </summary>
        public class ItemData
        {
            /// <summary>
            /// 显示的文本
            /// </summary>
            public string Text { get; set; }
            /// <summary>
            /// 前缀图片
            /// </summary>
            public Image Image { get; set; }

            /// <inheritdoc cref="ItemData"/>
            /// <param name="text"><inheritdoc cref="Text" path="/summary"/></param>
            public ItemData(string text)
            {
                Text = text;
            }

            /// <inheritdoc cref="ItemData"/>
            /// <param name="text"><inheritdoc cref="Text" path="/summary"/></param>
            /// <param name="image"><inheritdoc cref="Image" path="/summary"/></param>
            public ItemData(string text, Image image)
            {
                Text = text;
                Image = image;
            }

            /// <inheritdoc/>
            public override string ToString()
            {
                return Text;
            }
        }
    }
}
